home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 3 / Info_Mac_1994-01.iso / Development / General / GCC 1.37.1r15 / Machines / out-sparc.c < prev    next >
Text File  |  1990-03-14  |  54KB  |  1,988 lines

  1. /* Subroutines for insn-output.c for Sun SPARC.
  2.    Copyright (C) 1987, 1988, 1989 Free Software Foundation, Inc.
  3.    Contributed by Michael Tiemann (tiemann@mcc.com)
  4.  
  5. This file is part of GNU CC.
  6.  
  7. GNU CC is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 1, or (at your option)
  10. any later version.
  11.  
  12. GNU CC is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with GNU CC; see the file COPYING.  If not, write to
  19. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21. /* Global variables for machine-dependend things.  */
  22.  
  23. /* This should go away if we pass floats to regs via
  24.    the stack instead of the frame, and if we learn how
  25.    to renumber all the registers when we don't do a save (hard!).  */
  26. extern int frame_pointer_needed;
  27.  
  28. static rtx find_addr_reg ();
  29.  
  30. rtx next_real_insn_no_labels ();
  31.  
  32. /* Return non-zero only if OP is a register of mode MODE,
  33.    or const0_rtx.  */
  34. int
  35. reg_or_0_operand (op, mode)
  36.      rtx op;
  37.      enum machine_mode mode;
  38. {
  39.   return (op == const0_rtx || register_operand (op, mode));
  40. }
  41.  
  42. /* Return non-zero if this pattern, can be evaluated safely, even if it
  43.    was not asked for.  */
  44. int
  45. safe_insn_src_p (op, mode)
  46.      rtx op;
  47.      enum machine_mode mode;
  48. {
  49.   /* Just experimenting.  */
  50.  
  51.   /* No floating point src is safe if it contains an arithmetic
  52.      operation, since that operation may trap.  */
  53.   switch (GET_CODE (op))
  54.     {
  55.     case CONST_INT:
  56.     case LABEL_REF:
  57.     case SYMBOL_REF:
  58.     case CONST:
  59.       return 1;
  60.  
  61.     case REG:
  62.       return 1;
  63.  
  64.     case MEM:
  65.       return CONSTANT_ADDRESS_P (XEXP (op, 0));
  66.  
  67.       /* We never need to negate or complement constants.  */
  68.     case NEG:
  69.       return (mode != SFmode && mode != DFmode);
  70.     case NOT:
  71.       return 1;
  72.  
  73.     case COMPARE:
  74.     case MINUS:
  75.     case PLUS:
  76.       return (mode != SFmode && mode != DFmode);
  77.     case AND:
  78.     case IOR:
  79.     case XOR:
  80.     case LSHIFT:
  81.     case ASHIFT:
  82.     case ASHIFTRT:
  83.     case LSHIFTRT:
  84.       if ((GET_CODE (XEXP (op, 0)) == CONST_INT && ! SMALL_INT (XEXP (op, 0)))
  85.       || (GET_CODE (XEXP (op, 1)) == CONST_INT && ! SMALL_INT (XEXP (op, 1))))
  86.     return 0;
  87.       return 1;
  88.  
  89.     default:
  90.       return 0;
  91.     }
  92. }
  93.  
  94. /* Return 1 if REG is clobbered in IN.
  95.    Return 0 if REG is used in IN (other than being clobbered).
  96.    Return 2 if REG does not appear in IN.  */
  97.  
  98. static int
  99. reg_clobbered_p (reg, in)
  100.      rtx reg;
  101.      rtx in;
  102. {
  103.   register char *fmt;
  104.   register int i, result = 0;
  105.  
  106.   register enum rtx_code code;
  107.  
  108.   if (in == 0)
  109.     return 2;
  110.  
  111.   code = GET_CODE (in);
  112.  
  113.   switch (code)
  114.     {
  115.       /* Let these fail out quickly.  */
  116.     case CONST_INT:
  117.     case SYMBOL_REF:
  118.     case CONST:
  119.       return 2;
  120.  
  121.     case SUBREG:
  122.       if (SUBREG_WORD (in) != 0)
  123.     in = gen_rtx (REG, SImode, REGNO (SUBREG_REG (in)) + SUBREG_WORD (in));
  124.       else
  125.     in = SUBREG_REG (in);
  126.  
  127.     case REG:
  128.       if (in == reg
  129.       || refers_to_regno_p (REGNO (reg),
  130.                 REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
  131.                 in, 0))
  132.     return 0;
  133.       return 2;
  134.  
  135.     case SET:
  136.       if (SET_SRC (in) == reg
  137.       || refers_to_regno_p (REGNO (reg),
  138.                 REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
  139.                 SET_SRC (in), 0))
  140.     return 0;
  141.  
  142.       if (SET_DEST (in) == reg)
  143.     return 1;
  144.  
  145.       if (refers_to_regno_p (REGNO (reg),
  146.                  REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
  147.                  SET_DEST (in), 0))
  148.     if (GET_CODE (SET_DEST (in)) == REG
  149.         || GET_CODE (SET_DEST (in)) == SUBREG)
  150.       return 1;
  151.     else
  152.       return 0;
  153.       return 2;
  154.  
  155.     case USE:
  156.       if (XEXP (in, 0) == reg
  157.       || refers_to_regno_p (REGNO (reg),
  158.                 REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
  159.                 XEXP (in, 0), 0))
  160.     return 0;
  161.       return 2;
  162.  
  163.     case CLOBBER:
  164.       if (XEXP (in, 0) == reg)
  165.     return 1;
  166.       /* If the CLOBBER expression is a SUBREG, accept that as a
  167.      clobber.  But if it is some expression based on this register,
  168.      that is like a USE as far as this register is concerned,
  169.      so we won't take it.  */
  170.       if (refers_to_regno_p (REGNO (reg),
  171.                  REGNO (reg) + HARD_REGNO_NREGS (reg, GET_MODE (reg)),
  172.                  XEXP (in, 0), 0))
  173.     if (GET_CODE (XEXP (in, 0)) == REG
  174.         || GET_CODE (XEXP (in, 0)) == SUBREG)
  175.       return 1;
  176.     else
  177.       return 0;
  178.       return 2;
  179.     }
  180.  
  181.   fmt = GET_RTX_FORMAT (code);
  182.  
  183.   result = 2;
  184.  
  185.   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
  186.     {
  187.       if (fmt[i] == 'E')
  188.     {
  189.       register int j;
  190.       for (j = XVECLEN (in, i) - 1; j >= 0; j--)
  191.         switch (reg_clobbered_p (reg, XVECEXP (in, i, j)))
  192.           {
  193.           case 0:
  194.         return 0;
  195.           case 2:
  196.         continue;
  197.           case 1:
  198.         result = 1;
  199.         break;
  200.           }
  201.     }
  202.       else if (fmt[i] == 'e')
  203.     switch (reg_clobbered_p (reg, XEXP (in, i)))
  204.       {
  205.       case 0:
  206.         return 0;
  207.       case 2:
  208.         continue;
  209.       case 1:
  210.         result = 1;
  211.         break;
  212.       }
  213.     }
  214.   return result;
  215. }
  216.  
  217. /* Return non-zero if OP can be written to without screwing up
  218.    GCC's model of what's going on.  It is assumed that this operand
  219.    appears in the dest position of a SET insn in a conditional
  220.    branch's delay slot.  AFTER is the label to start looking from.  */
  221. int
  222. operand_clobbered_before_used_after (op, after)
  223.      rtx op;
  224.      rtx after;
  225. {
  226.   extern char call_used_regs[];
  227.  
  228.   /* Just experimenting.  */
  229.   if (GET_CODE (op) == CC0)
  230.     return 1;
  231.   if (GET_CODE (op) == REG)
  232.     {
  233.       rtx insn;
  234.  
  235.       if (op == stack_pointer_rtx)
  236.     return 0;
  237.  
  238.       for (insn = NEXT_INSN (after); insn; insn = NEXT_INSN (insn))
  239.     {
  240.       if (GET_CODE (insn) == NOTE)
  241.         continue;
  242.       if (GET_CODE (insn) == INSN
  243.           || GET_CODE (insn) == JUMP_INSN
  244.           || GET_CODE (insn) == CALL_INSN)
  245.         {
  246.           switch (reg_clobbered_p (op, PATTERN (insn)))
  247.         {
  248.         case 0:
  249.           return 0;
  250.         case 2:
  251.           break;
  252.         case 1:
  253.           return 1;
  254.         }
  255.           if (dead_or_set_p (insn, op))
  256.         return 1;
  257.         }
  258.       else if (GET_CODE (insn) == CODE_LABEL)
  259.         return 0;
  260.       if (GET_CODE (insn) == JUMP_INSN)
  261.         {
  262.           if (condjump_p (insn))
  263.         return 0;
  264.           /* This is a jump insn which has already
  265.          been mangled.  We can't tell what it does.  */
  266.           if (GET_CODE (PATTERN (insn)) == PARALLEL)
  267.         return 0;
  268.           if (! JUMP_LABEL (insn))
  269.         return 0;
  270.           /* Keep following jumps.  */
  271.           insn = JUMP_LABEL (insn);
  272.         }
  273.     }
  274.       return 1;
  275.     }
  276.  
  277.   /* In both of these cases, the first insn executed
  278.      for this op will be a sethi %hi(whatever),%g1,
  279.      which is tolerable.  */
  280.   if (GET_CODE (op) == MEM)
  281.     return (CONSTANT_ADDRESS_P (XEXP (op, 0)));
  282.  
  283.   return 0;
  284. }
  285.  
  286. /* Return non-zero if this pattern, as a source to a "SET",
  287.    is known to yield an instruction of unit size.  */
  288. int
  289. single_insn_src_p (op, mode)
  290.      rtx op;
  291.      enum machine_mode mode;
  292. {
  293.   switch (GET_CODE (op))
  294.     {
  295.     case CONST_INT:
  296. #if 1
  297.       /* This is not always a single insn src, technically,
  298.      but output_delayed_branch knows how to deal with it.  */
  299.       return 1;
  300. #else
  301.       if (SMALL_INT (op))
  302.     return 1;
  303.       /* We can put this set insn into delay slot, because this is one
  304.      insn; 'sethi'.  */
  305.       if ((INTVAL (op) & 0x3ff) == 0)
  306.     return 1;
  307.  
  308.       /* This is not a single insn src, technically,
  309.      but output_delayed_branch knows how to deal with it.  */
  310.       return 1;
  311. #endif
  312.  
  313. #if 1
  314.     case SYMBOL_REF:
  315.       /* This is not a single insn src, technically,
  316.      but output_delayed_branch knows how to deal with it.  */
  317.       return 1;
  318. #else
  319.       return 0;
  320. #endif
  321.  
  322.     case REG:
  323.       return 1;
  324.  
  325.     case MEM:
  326. #if 0
  327.       /* This is not a single insn src, technically,
  328.      but output_delayed_branch knows how to deal with it.  */
  329.       if (GET_CODE (XEXP (op, 0)) == SYMBOL_REF)
  330.     return 0;
  331. #endif
  332.       return 1;
  333.  
  334.       /* We never need to negate or complement constants.  */
  335.     case NEG:
  336.       return (mode != DFmode);
  337.     case NOT:
  338.       return 1;
  339.  
  340.     case COMPARE:
  341.     case MINUS:
  342.       /* If the target is cc0, then these insns will take
  343.      two insns (one being a nop).  */
  344.       return (mode != SFmode && mode != DFmode);
  345.     case PLUS:
  346.     case AND:
  347.     case IOR:
  348.     case XOR:
  349.     case LSHIFT:
  350.     case ASHIFT:
  351.     case ASHIFTRT:
  352.     case LSHIFTRT:
  353.       if ((GET_CODE (XEXP (op, 0)) == CONST_INT && ! SMALL_INT (XEXP (op, 0)))
  354.       || (GET_CODE (XEXP (op, 1)) == CONST_INT && ! SMALL_INT (XEXP (op, 1))))
  355.     return 0;
  356.       return 1;
  357.  
  358.     case SUBREG:
  359.       if (SUBREG_WORD (op) != 0)
  360.     return 0;
  361.       return single_insn_src_p (SUBREG_REG (op), mode);
  362.  
  363.     case SIGN_EXTEND:
  364.     case ZERO_EXTEND:
  365.       /* Lazy... could check for more cases.  */
  366.       if (GET_CODE (XEXP (op, 0)) == MEM
  367.       && ! CONSTANT_ADDRESS_P (XEXP (XEXP (op, 0), 0)))
  368.     return 1;
  369.       return 0;
  370.  
  371.       /* Not doing floating point, since they probably
  372.      take longer than the branch slot they might fill.  */
  373.     case FLOAT_EXTEND:
  374.     case FLOAT_TRUNCATE:
  375.     case FLOAT:
  376.     case FIX:
  377.     case UNSIGNED_FLOAT:
  378.     case UNSIGNED_FIX:
  379.       return 0;
  380.  
  381.     default:
  382.       return 0;
  383.     }
  384. }
  385.  
  386. /* This extra test must be done to verify that a move insn
  387.    really is just one assembler insn.  */
  388.  
  389. int
  390. single_insn_extra_test (dest, src)
  391.      rtx dest, src;
  392. {
  393.   /* Moves between FP regs and CPU regs are two insns.  */
  394.   return (!(GET_CODE (src) == REG
  395.         && GET_CODE (dest) == REG
  396.         && (FP_REG_P (src) != FP_REG_P (dest))));
  397. }
  398.  
  399. /* Nonzero only if this *really* is a single insn operand.  */
  400. int
  401. strict_single_insn_op_p (op, mode)
  402.      rtx op;
  403.      enum machine_mode mode;
  404. {
  405.   if (mode == VOIDmode)
  406.     mode = GET_MODE (op);
  407.  
  408.   switch (GET_CODE (op))
  409.     {
  410.     case CC0:
  411.       return 1;
  412.  
  413.     case CONST_INT:
  414.       if (SMALL_INT (op))
  415.     return 1;
  416.       /* We can put this set insn into delay slot, because this is one
  417.      insn; 'sethi'.  */
  418.       if ((INTVAL (op) & 0x3ff) == 0)
  419.     return 1;
  420.       return 0;
  421.  
  422.     case SYMBOL_REF:
  423.       return 0;
  424.  
  425.     case REG:
  426.       return (mode != DFmode && mode != DImode);
  427.  
  428.     case MEM:
  429.       if (! CONSTANT_ADDRESS_P (XEXP (op, 0)))
  430.     return (mode != DFmode && mode != DImode);
  431.       return 0;
  432.  
  433.       /* We never need to negate or complement constants.  */
  434.     case NEG:
  435.       return (mode != DFmode);
  436.     case NOT:
  437.       return 1;
  438.  
  439.     case COMPARE:
  440.     case MINUS:
  441.       /* If the target is cc0, then these insns will take
  442.      two insns (one being a nop).  */
  443.       return (mode != SFmode && mode != DFmode);
  444.     case PLUS:
  445.     case AND:
  446.     case IOR:
  447.     case XOR:
  448.     case LSHIFT:
  449.     case ASHIFT:
  450.     case ASHIFTRT:
  451.     case LSHIFTRT:
  452.       if ((GET_CODE (XEXP (op, 0)) == CONST_INT && ! SMALL_INT (XEXP (op, 0)))
  453.       || (GET_CODE (XEXP (op, 1)) == CONST_INT && ! SMALL_INT (XEXP (op, 1))))
  454.     return 0;
  455.       return 1;
  456.  
  457.     case SUBREG:
  458.       if (SUBREG_WORD (op) != 0)
  459.     return 0;
  460.       return strict_single_insn_op_p (SUBREG_REG (op), mode);
  461.  
  462.     case SIGN_EXTEND:
  463.     case ZERO_EXTEND:
  464.       if (GET_CODE (XEXP (op, 0)) == MEM
  465.       && ! CONSTANT_ADDRESS_P (XEXP (XEXP (op, 0), 0)))
  466.     return 1;
  467.       return 0;
  468.  
  469.       /* Not doing floating point, since they probably
  470.      take longer than the branch slot they might fill.  */
  471.     case FLOAT_EXTEND:
  472.     case FLOAT_TRUNCATE:
  473.     case FLOAT:
  474.     case FIX:
  475.     case UNSIGNED_FLOAT:
  476.     case UNSIGNED_FIX:
  477.       return 0;
  478.  
  479.     default:
  480.       return 0;
  481.     }
  482. }
  483.  
  484. /* Return truth value of whether OP is a relational operator.  */
  485. int
  486. relop (op, mode)
  487.      rtx op;
  488.      enum machine_mode mode;
  489. {
  490.   switch (GET_CODE (op))
  491.     {
  492.     case EQ:
  493.     case NE:
  494.     case GT:
  495.     case GE:
  496.     case LT:
  497.     case LE:
  498.     case GTU:
  499.     case GEU:
  500.     case LTU:
  501.     case LEU:
  502.       return 1;
  503.     }
  504.   return 0;
  505. }
  506.  
  507. /* Return truth value of wheterh OP is EQ or NE.  */
  508. int
  509. eq_or_neq (op, mode)
  510.      rtx op;
  511.      enum machine_mode mode;
  512. {
  513.   return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
  514. }
  515.  
  516. /* Return truth value of whether OP can be used as an operands in a three
  517.    address arithmetic insn (such as add %o1,7,%l2) of mode MODE.  */
  518.  
  519. int
  520. arith_operand (op, mode)
  521.      rtx op;
  522.      enum machine_mode mode;
  523. {
  524.   return (register_operand (op, mode)
  525.       || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
  526. }
  527.  
  528. /* Return truth value of whether OP can be used as an operand in a two
  529.    address arithmetic insn (such as set 123456,%o4) of mode MODE.  */
  530.  
  531. int
  532. arith32_operand (op, mode)
  533.      rtx op;
  534.      enum machine_mode mode;
  535. {
  536.   return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
  537. }
  538.  
  539. /* Return truth value of whether OP is a integer which fits the
  540.    range constraining immediate operands in three-address insns.  */
  541.  
  542. int
  543. small_int (op, mode)
  544.      rtx op;
  545.      enum machine_mode mode;
  546. {
  547.   return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
  548. }
  549.  
  550. /* Return the best assembler insn template
  551.    for moving operands[1] into operands[0] as a fullword.  */
  552.  
  553. static char *
  554. singlemove_string (operands)
  555.      rtx *operands;
  556. {
  557.   if (GET_CODE (operands[0]) == MEM)
  558.     {
  559.       if (GET_CODE (operands[1]) != MEM)
  560.     if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
  561.       {
  562.         if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  563.            && cc_prev_status.mdep == XEXP (operands[0], 0)))
  564.           output_asm_insn ("sethi %%hi(%m0),%%g1", operands);
  565.         cc_status.flags |= CC_KNOW_HI_G1;
  566.         cc_status.mdep = XEXP (operands[0], 0);
  567.         return "st %1,[%%lo(%m0)+%%g1]";
  568.       }
  569.     else
  570.       return "st %r1,%0";
  571.       else
  572.     {
  573.       rtx xoperands[2];
  574.  
  575.       cc_status.flags &= ~CC_F0_IS_0;
  576.       xoperands[0] = gen_rtx (REG, SFmode, 32);
  577.       xoperands[1] = operands[1];
  578.       output_asm_insn (singlemove_string (xoperands), xoperands);
  579.       xoperands[1] = xoperands[0];
  580.       xoperands[0] = operands[0];
  581.       output_asm_insn (singlemove_string (xoperands), xoperands);
  582.       return "";
  583.     }
  584.     }
  585.   if (GET_CODE (operands[1]) == MEM)
  586.     {
  587.       if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
  588.     {
  589.       if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  590.          && cc_prev_status.mdep == XEXP (operands[1], 0)))
  591.         output_asm_insn ("sethi %%hi(%m1),%%g1", operands);
  592.       cc_status.flags |= CC_KNOW_HI_G1;
  593.       cc_status.mdep = XEXP (operands[1], 0);
  594.       return "ld [%%lo(%m1)+%%g1],%0";
  595.     }
  596.       return "ld %1,%0";
  597.     }
  598.   return "mov %1,%0";
  599. }
  600.  
  601. /* Output assembler code to perform a doubleword move insn
  602.    with operands OPERANDS.  */
  603.  
  604. char *
  605. output_move_double (operands)
  606.      rtx *operands;
  607. {
  608.   enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
  609.   rtx latehalf[2];
  610.   rtx addreg0 = 0, addreg1 = 0;
  611.  
  612.   /* First classify both operands.  */
  613.  
  614.   if (REG_P (operands[0]))
  615.     optype0 = REGOP;
  616.   else if (offsettable_memref_p (operands[0]))
  617.     optype0 = OFFSOP;
  618.   else if (GET_CODE (operands[0]) == MEM)
  619.     optype0 = MEMOP;
  620.   else
  621.     optype0 = RNDOP;
  622.  
  623.   if (REG_P (operands[1]))
  624.     optype1 = REGOP;
  625.   else if (CONSTANT_P (operands[1])
  626.        || GET_CODE (operands[1]) == CONST_DOUBLE)
  627.     optype1 = CNSTOP;
  628.   else if (offsettable_memref_p (operands[1]))
  629.     optype1 = OFFSOP;
  630.   else if (GET_CODE (operands[1]) == MEM)
  631.     optype1 = MEMOP;
  632.   else
  633.     optype1 = RNDOP;
  634.  
  635.   /* Check for the cases that the operand constraints are not
  636.      supposed to allow to happen.  Abort if we get one,
  637.      because generating code for these cases is painful.  */
  638.  
  639.   if (optype0 == RNDOP || optype1 == RNDOP)
  640.     abort ();
  641.  
  642.   /* If an operand is an unoffsettable memory ref, find a register
  643.      we can increment temporarily to make it refer to the second word.  */
  644.  
  645.   if (optype0 == MEMOP)
  646.     addreg0 = find_addr_reg (XEXP (operands[0], 0));
  647.  
  648.   if (optype1 == MEMOP)
  649.     addreg1 = find_addr_reg (XEXP (operands[1], 0));
  650.  
  651.   /* Ok, we can do one word at a time.
  652.      Normally we do the low-numbered word first,
  653.      but if either operand is autodecrementing then we
  654.      do the high-numbered word first.
  655.  
  656.      In either case, set up in LATEHALF the operands to use
  657.      for the high-numbered word and in some cases alter the
  658.      operands in OPERANDS to be suitable for the low-numbered word.  */
  659.  
  660.   if (optype0 == REGOP)
  661.     latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
  662.   else if (optype0 == OFFSOP)
  663.     latehalf[0] = adj_offsettable_operand (operands[0], 4);
  664.   else
  665.     latehalf[0] = operands[0];
  666.  
  667.   if (optype1 == REGOP)
  668.     latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
  669.   else if (optype1 == OFFSOP)
  670.     latehalf[1] = adj_offsettable_operand (operands[1], 4);
  671.   else if (optype1 == CNSTOP)
  672.     {
  673.       if (CONSTANT_P (operands[1]))
  674.     latehalf[1] = const0_rtx;
  675.       else if (GET_CODE (operands[1]) == CONST_DOUBLE)
  676.     {
  677.       latehalf[1] = gen_rtx (CONST_INT, VOIDmode,
  678.                  CONST_DOUBLE_HIGH (operands[1]));
  679.       operands[1] = gen_rtx (CONST_INT, VOIDmode,
  680.                  CONST_DOUBLE_LOW (operands[1]));
  681.     }
  682.     }
  683.   else
  684.     latehalf[1] = operands[1];
  685.  
  686.   /* If the first move would clobber the source of the second one,
  687.      do them in the other order.
  688.  
  689.      RMS says "This happens only for registers;
  690.      such overlap can't happen in memory unless the user explicitly
  691.      sets it up, and that is an undefined circumstance."
  692.  
  693.      but it happens on the sparc when loading parameter registers,
  694.      so I am going to define that circumstance, and make it work
  695.      as expected.  */
  696.  
  697.   /* Easy case: try moving both words at once.  */
  698.   /* First check for moving between an even/odd register pair
  699.      and a memory location.  */
  700.   if ((optype0 == REGOP && optype1 != REGOP && optype1 != CNSTOP
  701.        && (REGNO (operands[0]) & 1) == 0)
  702.       || (optype0 != REGOP && optype1 != CNSTOP && optype1 == REGOP
  703.       && (REGNO (operands[1]) & 1) == 0))
  704.     {
  705.       rtx op1, op2;
  706.       rtx base = 0, offset = const0_rtx;
  707.  
  708.       /* OP1 gets the register pair, and OP2 gets the memory address.  */
  709.       if (optype0 == REGOP)
  710.     op1 = operands[0], op2 = XEXP (operands[1], 0);
  711.       else
  712.     op1 = operands[1], op2 = XEXP (operands[0], 0);
  713.  
  714.       /* Now see if we can trust the address to be 8-byte aligned.  */
  715.       /* Trust global variables.  */
  716.       if (CONSTANT_ADDRESS_P (op2))
  717.     {
  718.       operands[0] = op1;
  719.       operands[1] = op2;
  720.       if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  721.          && cc_prev_status.mdep == op2))
  722.         output_asm_insn ("sethi %%hi(%1),%%g1", operands);
  723.       cc_status.flags |= CC_KNOW_HI_G1;
  724.       cc_status.mdep = op2;
  725.       if (op1 == operands[0])
  726.         return "ldd [%%lo(%1)+%%g1],%0";
  727.       else
  728.         return "std [%%lo(%1)+%%g1],%0";
  729.     }
  730.  
  731.       if (GET_CODE (op2) == PLUS)
  732.     {
  733.       if (GET_CODE (XEXP (op2, 0)) == REG)
  734.         base = XEXP (op2, 0), offset = XEXP (op2, 1);
  735.       else if (GET_CODE (XEXP (op2, 1)) == REG)
  736.         base = XEXP (op2, 1), offset = XEXP (op2, 0);
  737.     }
  738.  
  739.       /* Trust round enough offsets from the stack or frame pointer.  */
  740.       if (base
  741.       && (REGNO (base) == FRAME_POINTER_REGNUM
  742.           || REGNO (base) == STACK_POINTER_REGNUM))
  743.     {
  744.       if (GET_CODE (offset) == CONST_INT
  745.           && (INTVAL (offset) & 0x7) == 0)
  746.         {
  747.           if (op1 == operands[0])
  748.         return "ldd %1,%0";
  749.           else
  750.         return "std %1,%0";
  751.         }
  752.     }
  753.       else
  754.     {
  755.       /* We know structs not on the stack are properly aligned.
  756.          Since a double asks for 8-byte alignment,
  757.          we know it must have got that if it is in a struct.
  758.          But a DImode need not be 8-byte aligned, because it could be a
  759.          struct containing two ints or pointers.  */
  760.  
  761.       /* Sun fucks us here.  We cannot trust references
  762.          to doubles via varying addresses.  It might be on the stack
  763.          even if we don't know that it is; and then it might not be
  764.          double-word aligned.  */
  765. #if 0
  766.       if (GET_CODE (operands[1]) == MEM && GET_MODE (operands[1]) == DFmode
  767.           && MEM_IN_STRUCT_P (operands[1]))
  768.         return "ldd %1,%0";
  769.       else if (GET_CODE (operands[0]) == MEM
  770.            && GET_MODE (operands[0]) == DFmode
  771.            && MEM_IN_STRUCT_P (operands[0]))
  772.         return "std %1,%0";
  773. #endif
  774.     }
  775.     }
  776.  
  777.   if (optype0 == REGOP && optype1 == REGOP
  778.       && REGNO (operands[0]) == REGNO (latehalf[1]))
  779.     {
  780.       /* Make any unoffsettable addresses point at high-numbered word.  */
  781.       if (addreg0)
  782.     output_asm_insn ("add %0,0x4,%0", &addreg0);
  783.       if (addreg1)
  784.     output_asm_insn ("add %0,0x4,%0", &addreg1);
  785.  
  786.       /* Do that word.  */
  787.       output_asm_insn (singlemove_string (latehalf), latehalf);
  788.  
  789.       /* Undo the adds we just did.  */
  790.       if (addreg0)
  791.     output_asm_insn ("add %0,-0x4,%0", &addreg0);
  792.       if (addreg1)
  793.     output_asm_insn ("add %0,-0x4,%0", &addreg0);
  794.  
  795.       /* Do low-numbered word.  */
  796.       return singlemove_string (operands);
  797.     }
  798.   else if (optype0 == REGOP && optype1 != REGOP
  799.        && reg_overlap_mentioned_p (operands[0], operands[1]))
  800.     {
  801.       /* Do the late half first.  */
  802.       output_asm_insn (singlemove_string (latehalf), latehalf);
  803.       /* Then clobber.  */
  804.       return singlemove_string (operands);
  805.     }
  806.  
  807.   /* Normal case: do the two words, low-numbered first.  */
  808.  
  809.   output_asm_insn (singlemove_string (operands), operands);
  810.  
  811.   /* Make any unoffsettable addresses point at high-numbered word.  */
  812.   if (addreg0)
  813.     output_asm_insn ("add %0,0x4,%0", &addreg0);
  814.   if (addreg1)
  815.     output_asm_insn ("add %0,0x4,%0", &addreg1);
  816.  
  817.   /* Do that word.  */
  818.   output_asm_insn (singlemove_string (latehalf), latehalf);
  819.  
  820.   /* Undo the adds we just did.  */
  821.   if (addreg0)
  822.     output_asm_insn ("add %0,-0x4,%0", &addreg0);
  823.   if (addreg1)
  824.     output_asm_insn ("add %0,-0x4,%0", &addreg1);
  825.  
  826.   return "";
  827. }
  828.  
  829. static char *
  830. output_fp_move_double (operands)
  831.      rtx *operands;
  832. {
  833.   if (FP_REG_P (operands[0]))
  834.     {
  835.       if (FP_REG_P (operands[1]))
  836.     {
  837.       output_asm_insn ("fmovs %1,%0", operands);
  838.       operands[0] = gen_rtx (REG, VOIDmode, REGNO (operands[0]) + 1);
  839.       operands[1] = gen_rtx (REG, VOIDmode, REGNO (operands[1]) + 1);
  840.       return "fmovs %1,%0";
  841.     }
  842.       if (GET_CODE (operands[1]) == REG)
  843.     {
  844.       if ((REGNO (operands[1]) & 1) == 0)
  845.         return "std %1,[%%fp-8]\n\tldd [%%fp-8],%0";
  846.       else
  847.         {
  848.           rtx xoperands[3];
  849.           xoperands[0] = operands[0];
  850.           xoperands[1] = operands[1];
  851.           xoperands[2] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
  852.           output_asm_insn ("st %2,[%%fp-4]\n\tst %1,[%%fp-8]\n\tldd [%%fp-8],%0", xoperands);
  853.           return "";
  854.         }
  855.     }
  856.       /* Use ldd if known to be aligned.  */
  857.       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
  858.       && (((XEXP (XEXP (operands[1], 0), 0) == frame_pointer_rtx
  859.         || XEXP (XEXP (operands[1], 0), 0) == stack_pointer_rtx)
  860.            && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT
  861.            && (INTVAL (XEXP (XEXP (operands[1], 0), 1)) & 0x7) == 0)
  862.           /* Arrays are known to be aligned,
  863.          and reg+reg addresses are used (on this machine)
  864.          only for array accesses.  */
  865.           || (REG_P (XEXP (XEXP (operands[1], 0), 0))
  866.           && REG_P (XEXP (XEXP (operands[1], 0), 1)))))
  867.     return "ldd %1,%0";
  868.       if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
  869.     {
  870.       if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  871.          && cc_prev_status.mdep == XEXP (operands[1], 0)))
  872.         output_asm_insn ("sethi %%hi(%m1),%%g1", operands);
  873.       cc_status.flags |= CC_KNOW_HI_G1;
  874.       cc_status.mdep = XEXP (operands[1], 0);
  875.       return "ldd [%%lo(%m1)+%%g1],%0";
  876.     }
  877.       /* Otherwise use two ld insns.  */
  878.       {
  879.     rtx xoperands[2];
  880.     output_asm_insn ("ld %1,%0", operands);
  881.     xoperands[0] = gen_rtx (REG, GET_MODE (operands[0]),
  882.                 REGNO (operands[0]) + 1);
  883.     xoperands[1] = gen_rtx (MEM, GET_MODE (operands[1]),
  884.                 plus_constant (XEXP (operands[1], 0), 4));
  885.     output_asm_insn ("ld %1,%0", xoperands);
  886.     return "";
  887.       }
  888.     }
  889.   else if (FP_REG_P (operands[1]))
  890.     {
  891.       if (GET_CODE (operands[0]) == REG)
  892.     {
  893.       if ((REGNO (operands[0]) & 1) == 0)
  894.         return "std %1,[%%fp-8]\n\tldd [%%fp-8],%0";
  895.       else
  896.         {
  897.           rtx xoperands[3];
  898.           xoperands[2] = operands[1];
  899.           xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
  900.           xoperands[0] = operands[0];
  901.           output_asm_insn ("std %2,[%%fp-8]\n\tld [%%fp-4],%1\n\tld [%%fp-8],%0", xoperands);
  902.           return "";
  903.         }
  904.     }
  905.       /* Use std if we can be sure it is well-aligned.  */
  906.       if (GET_CODE (XEXP (operands[0], 0)) == PLUS
  907.       && (((XEXP (XEXP (operands[0], 0), 0) == frame_pointer_rtx
  908.         || XEXP (XEXP (operands[0], 0), 0) == stack_pointer_rtx)
  909.            && GET_CODE (XEXP (XEXP (operands[0], 0), 1)) == CONST_INT
  910.            && (INTVAL (XEXP (XEXP (operands[0], 0), 1)) & 0x7) == 0)
  911.           /* Arrays are known to be aligned,
  912.          and reg+reg addresses are used (on this machine)
  913.          only for array accesses.  */
  914.           || (REG_P (XEXP (XEXP (operands[0], 0), 0))
  915.           && REG_P (XEXP (XEXP (operands[0], 0), 1)))))
  916.     return "std %1,%0";
  917.       if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
  918.     {
  919.       if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  920.          && cc_prev_status.mdep == XEXP (operands[0], 0)))
  921.         output_asm_insn ("sethi %%hi(%m0),%%g1", operands);
  922.       cc_status.flags |= CC_KNOW_HI_G1;
  923.       cc_status.mdep = XEXP (operands[0], 0);
  924.       return "std %1,[%%lo(%m0)+%%g1]";
  925.     }
  926.       /* Otherwise use two st insns.  */
  927.       {
  928.     rtx xoperands[2];
  929.     output_asm_insn ("st %r1,%0", operands);
  930.     xoperands[1] = gen_rtx (REG, GET_MODE (operands[1]),
  931.                 REGNO (operands[1]) + 1);
  932.     xoperands[0] = gen_rtx (MEM, GET_MODE (operands[0]),
  933.                 plus_constant (XEXP (operands[0], 0), 4));
  934.     output_asm_insn ("st %r1,%0", xoperands);
  935.     return "";
  936.       }
  937.     }
  938.   else abort ();
  939. }
  940.  
  941. /* Return a REG that occurs in ADDR with coefficient 1.
  942.    ADDR can be effectively incremented by incrementing REG.  */
  943.  
  944. static rtx
  945. find_addr_reg (addr)
  946.      rtx addr;
  947. {
  948.   while (GET_CODE (addr) == PLUS)
  949.     {
  950.       if (GET_CODE (XEXP (addr, 0)) == REG)
  951.     addr = XEXP (addr, 0);
  952.       else if (GET_CODE (XEXP (addr, 1)) == REG)
  953.     addr = XEXP (addr, 1);
  954.       else if (CONSTANT_P (XEXP (addr, 0)))
  955.     addr = XEXP (addr, 1);
  956.       else if (CONSTANT_P (XEXP (addr, 1)))
  957.     addr = XEXP (addr, 0);
  958.       else
  959.     abort ();
  960.     }
  961.   if (GET_CODE (addr) == REG)
  962.     return addr;
  963.   abort ();
  964. }
  965.  
  966. void
  967. output_sized_memop (opname, mode)
  968.      char *opname;
  969.      enum machine_mode mode;
  970. {
  971.   extern struct _iobuf *asm_out_file;
  972.  
  973.   static char *ld_size_suffix[] = { "ub", "uh", "", "?", "d" };
  974.   static char *st_size_suffix[] = { "b", "h", "", "?", "d" };
  975.   char *modename
  976.     = (opname[0] == 'l' ? ld_size_suffix : st_size_suffix)[GET_MODE_SIZE (mode) >> 1];
  977.  
  978.   fprintf (asm_out_file, "\t%s%s", opname, modename);
  979. }
  980.  
  981. /* Output a store-in-memory whose operands are OPERANDS[0,1].
  982.    OPERANDS[0] is a MEM, and OPERANDS[1] is a reg or zero.  */
  983.  
  984. char *
  985. output_store (operands)
  986.      rtx *operands;
  987. {
  988.   enum machine_mode mode = GET_MODE (operands[0]);
  989.   rtx address = XEXP (operands[0], 0);
  990.  
  991.   cc_status.flags |= CC_KNOW_HI_G1;
  992.   cc_status.mdep = address;
  993.  
  994.   if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  995.      && address == cc_prev_status.mdep))
  996.     {
  997.       output_asm_insn ("sethi %%hi(%m0),%%g1", operands);
  998.       cc_prev_status.mdep = address;
  999.     }
  1000.  
  1001.   /* Store zero in two parts when appropriate.  */
  1002.   if (mode == DFmode && operands[1] == dconst0_rtx)
  1003.     {
  1004.       /* We can't cross a page boundary here because the
  1005.      SYMBOL_REF must be double word aligned, and for this
  1006.      to be the case, SYMBOL_REF+4 cannot cross.  */
  1007.       output_sized_memop ("st", SImode);
  1008.       output_asm_insn ("%r1,[%%g1+%%lo(%m0)]", operands);
  1009.       output_sized_memop ("st", SImode);
  1010.       return "%r1,[%%g1+%%lo(%m0)+4]";
  1011.     }
  1012.  
  1013.   /* Code below isn't smart enough to move a doubleword in two parts,
  1014.      so use output_move_double to do that in the cases that require it.  */
  1015.   if ((mode == DImode || mode == DFmode)
  1016.       && (GET_CODE (operands[1]) == REG
  1017.       && (REGNO (operands[1]) & 1)))
  1018.     return output_move_double (operands);
  1019.  
  1020.   output_sized_memop ("st", mode);
  1021.   return "%r1,[%%g1+%%lo(%m0)]";
  1022. }
  1023.  
  1024. /* Output a fixed-point load-from-memory whose operands are OPERANDS[0,1].
  1025.    OPERANDS[0] is a reg, and OPERANDS[1] is a mem.  */
  1026.  
  1027. char *
  1028. output_load_fixed (operands)
  1029.      rtx *operands;
  1030. {
  1031.   enum machine_mode mode = GET_MODE (operands[0]);
  1032.   rtx address = XEXP (operands[1], 0);
  1033.  
  1034.   /* We don't bother trying to see if we know %hi(address).
  1035.      This is because we are doing a load, and if we know the
  1036.      %hi value, we probably also know that value in memory.  */
  1037.   cc_status.flags |= CC_KNOW_HI_G1;
  1038.   cc_status.mdep = address;
  1039.  
  1040.   if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  1041.      && address == cc_prev_status.mdep
  1042.      && cc_prev_status.mdep == cc_status.mdep))
  1043.     {
  1044.       output_asm_insn ("sethi %%hi(%m1),%%g1", operands);
  1045.       cc_prev_status.mdep = address;
  1046.     }
  1047.  
  1048.   /* Code below isn't smart enough to do a doubleword in two parts.
  1049.      So handle that case the slow way.  */
  1050.   if (mode == DImode
  1051.       && GET_CODE (operands[0]) == REG   /* Moving to nonaligned reg pair */
  1052.       && (REGNO (operands[0]) & 1))
  1053.     return output_move_double (operands);
  1054.  
  1055.   output_sized_memop ("ld", mode);
  1056.   if (GET_CODE (operands[0]) == REG)
  1057.     return "[%%g1+%%lo(%m1)],%0";
  1058.   abort ();
  1059. }
  1060.  
  1061. /* Output a floating-point load-from-memory whose operands are OPERANDS[0,1].
  1062.    OPERANDS[0] is a reg, and OPERANDS[1] is a mem.
  1063.    We also handle the case where OPERANDS[0] is a mem.  */
  1064.  
  1065. char *
  1066. output_load_floating (operands)
  1067.      rtx *operands;
  1068. {
  1069.   enum machine_mode mode = GET_MODE (operands[0]);
  1070.   rtx address = XEXP (operands[1], 0);
  1071.  
  1072.   /* We don't bother trying to see if we know %hi(address).
  1073.      This is because we are doing a load, and if we know the
  1074.      %hi value, we probably also know that value in memory.  */
  1075.   cc_status.flags |= CC_KNOW_HI_G1;
  1076.   cc_status.mdep = address;
  1077.  
  1078.   if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  1079.      && address == cc_prev_status.mdep
  1080.      && cc_prev_status.mdep == cc_status.mdep))
  1081.     {
  1082.       output_asm_insn ("sethi %%hi(%m1),%%g1", operands);
  1083.       cc_prev_status.mdep = address;
  1084.     }
  1085.  
  1086.   if (mode == DFmode)
  1087.     {
  1088.       if (REG_P (operands[0]))
  1089.     {
  1090.       if (REGNO (operands[0]) & 1)
  1091.         return output_move_double (operands);
  1092.       else
  1093.         return "ldd [%%g1+%%lo(%m1)],%0";
  1094.     }
  1095.       cc_status.flags &= ~(CC_F0_IS_0|CC_F1_IS_0);
  1096.       output_asm_insn ("ldd [%%g1+%%lo(%m1)],%%f0", operands);
  1097.       operands[1] = gen_rtx (REG, DFmode, 32);
  1098.       return output_fp_move_double (operands);
  1099.     }
  1100.  
  1101.   if (GET_CODE (operands[0]) == MEM)
  1102.     {
  1103.       cc_status.flags &= ~CC_F1_IS_0;
  1104.       output_asm_insn ("ld [%%g1+%%lo(%1)],%%f1", operands);
  1105.       if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
  1106.     {
  1107.       cc_status.mdep = XEXP (operands[0], 0);
  1108.       return "sethi %%hi(%m0),%%g1\n\tst %%f1,[%%g1+%%lo(%m0)]";
  1109.     }
  1110.       else
  1111.     return "st %%f1,%0";
  1112.     }
  1113.   return "ld [%%g1+%%lo(%m1)],%0";
  1114. }
  1115.  
  1116. /* Load the address specified by OPERANDS[3] into the register
  1117.    specified by OPERANDS[0].
  1118.  
  1119.    OPERANDS[3] may be the result of a sum, hence it could either be:
  1120.  
  1121.    (1) CONST
  1122.    (2) REG
  1123.    (2) REG + CONST_INT
  1124.    (3) REG + REG + CONST_INT
  1125.    (4) REG + REG  (special case of 3).
  1126.  
  1127.    Note that (3) is not a legitimate address.
  1128.    All cases are handled here.  */
  1129.  
  1130. void
  1131. output_load_address (operands)
  1132.      rtx *operands;
  1133. {
  1134.   rtx base, offset;
  1135.  
  1136.   if (CONSTANT_P (operands[3]))
  1137.     {
  1138.       output_asm_insn ("set %3,%0", operands);
  1139.       return;
  1140.     }
  1141.  
  1142.   if (REG_P (operands[3]))
  1143.     {
  1144.       if (REGNO (operands[0]) != REGNO (operands[3]))
  1145.     output_asm_insn ("mov %3,%0", operands);
  1146.       return;
  1147.     }
  1148.  
  1149.   if (GET_CODE (operands[3]) != PLUS)
  1150.     abort ();
  1151.  
  1152.   base = XEXP (operands[3], 0);
  1153.   offset = XEXP (operands[3], 1);
  1154.  
  1155.   if (GET_CODE (base) == CONST_INT)
  1156.     {
  1157.       rtx tmp = base;
  1158.       base = offset;
  1159.       offset = tmp;
  1160.     }
  1161.  
  1162.   if (GET_CODE (offset) != CONST_INT)
  1163.     {
  1164.       /* Operand is (PLUS (REG) (REG)).  */
  1165.       base = operands[3];
  1166.       offset = const0_rtx;
  1167.     }
  1168.  
  1169.   if (REG_P (base))
  1170.     {
  1171.       operands[6] = base;
  1172.       operands[7] = offset;
  1173.       if (SMALL_INT (offset))
  1174.     output_asm_insn ("add %6,%7,%0", operands);
  1175.       else
  1176.     output_asm_insn ("set %7,%0\n\tadd %0,%6,%0", operands);
  1177.     }
  1178.   else if (GET_CODE (base) == PLUS)
  1179.     {
  1180.       operands[6] = XEXP (base, 0);
  1181.       operands[7] = XEXP (base, 1);
  1182.       operands[8] = offset;
  1183.  
  1184.       if (SMALL_INT (offset))
  1185.     output_asm_insn ("add %6,%7,%0\n\tadd %0,%8,%0", operands);
  1186.       else
  1187.     output_asm_insn ("set %8,%0\n\tadd %0,%6,%0\n\tadd %0,%7,%0", operands);
  1188.     }
  1189.   else
  1190.     abort ();
  1191. }
  1192.  
  1193. /* Output code to place a size count SIZE in register REG.
  1194.    ALIGN is the size of the unit of transfer.
  1195.  
  1196.    Because block moves are pipelined, we don't include the
  1197.    first element in the transfer of SIZE to REG.  */
  1198.  
  1199. static void
  1200. output_size_for_block_move (size, reg, align)
  1201.      rtx size, reg;
  1202.      rtx align;
  1203. {
  1204.   rtx xoperands[3];
  1205.  
  1206.   xoperands[0] = reg;
  1207.   xoperands[1] = size;
  1208.   xoperands[2] = align;
  1209.   if (GET_CODE (size) == REG)
  1210.     output_asm_insn ("sub %1,%2,%0", xoperands);
  1211.   else
  1212.     {
  1213.       xoperands[1]
  1214.     = gen_rtx (CONST_INT, VOIDmode, INTVAL (size) - INTVAL (align));
  1215.       cc_status.flags &= ~ CC_KNOW_HI_G1;
  1216.       output_asm_insn ("set %1,%0", xoperands);
  1217.     }
  1218. }
  1219.  
  1220. /* Emit code to perform a block move.
  1221.  
  1222.    OPERANDS[0] is the destination.
  1223.    OPERANDS[1] is the source.
  1224.    OPERANDS[2] is the size.
  1225.    OPERANDS[3] is the alignment safe to use.
  1226.    OPERANDS[4] is a register we can safely clobber as a temp.  */
  1227.  
  1228. char *
  1229. output_block_move (operands)
  1230.      rtx *operands;
  1231. {
  1232.   /* A vector for our computed operands.  Note that load_output_address
  1233.      makes use of (and can clobber) up to the 8th element of this vector.  */
  1234.   rtx xoperands[10];
  1235.   rtx zoperands[10];
  1236.   static int movstrsi_label = 0;
  1237.   int i, j;
  1238.   rtx temp1 = operands[4];
  1239.   rtx alignrtx = operands[3];
  1240.   int align = INTVAL (alignrtx);
  1241.  
  1242.   xoperands[0] = operands[0];
  1243.   xoperands[1] = operands[1];
  1244.   xoperands[2] = temp1;
  1245.  
  1246.   /* We can't move more than four bytes at a time
  1247.      because we have only one register to move them through.  */
  1248.   if (align > 4)
  1249.     {
  1250.       align = 4;
  1251.       alignrtx = gen_rtx (CONST_INT, VOIDmode, 4);
  1252.     }
  1253.  
  1254.   /* Since we clobber untold things, nix the condition codes.  */
  1255.   CC_STATUS_INIT;
  1256.  
  1257.   /* Recognize special cases of block moves.  These occur
  1258.      when GNU C++ is forced to treat something as BLKmode
  1259.      to keep it in memory, when its mode could be represented
  1260.      with something smaller.
  1261.  
  1262.      We cannot do this for global variables, since we don't know
  1263.      what pages they don't cross.  Sigh.  */
  1264.   if (GET_CODE (operands[2]) == CONST_INT
  1265.       && INTVAL (operands[2]) <= 16
  1266.       && ! CONSTANT_ADDRESS_P (operands[0])
  1267.       && ! CONSTANT_ADDRESS_P (operands[1]))
  1268.     {
  1269.       int size = INTVAL (operands[2]);
  1270.  
  1271.       cc_status.flags &= ~CC_KNOW_HI_G1;
  1272.       if (align == 1)
  1273.     {
  1274.       if (memory_address_p (QImode, plus_constant (xoperands[0], size))
  1275.           && memory_address_p (QImode, plus_constant (xoperands[1], size)))
  1276.         {
  1277.           /* We will store different integers into this particular RTX.  */
  1278.           xoperands[2] = gen_rtx (CONST_INT, VOIDmode, 13);
  1279.           for (i = size-1; i >= 0; i--)
  1280.         {
  1281.           INTVAL (xoperands[2]) = i;
  1282.           output_asm_insn ("ldub [%a1+%2],%%g1\n\tstb %%g1,[%a0+%2]",
  1283.                    xoperands);
  1284.         }
  1285.           return "";
  1286.         }
  1287.     }
  1288.       else if (align == 2)
  1289.     {
  1290.       if (memory_address_p (HImode, plus_constant (xoperands[0], size))
  1291.           && memory_address_p (HImode, plus_constant (xoperands[1], size)))
  1292.         {
  1293.           /* We will store different integers into this particular RTX.  */
  1294.           xoperands[2] = gen_rtx (CONST_INT, VOIDmode, 13);
  1295.           for (i = (size>>1)-1; i >= 0; i--)
  1296.         {
  1297.           INTVAL (xoperands[2]) = i<<1;
  1298.           output_asm_insn ("lduh [%a1+%2],%%g1\n\tsth %%g1,[%a0+%2]",
  1299.                    xoperands);
  1300.         }
  1301.           return "";
  1302.         }
  1303.     }
  1304.       else
  1305.     {
  1306.       if (memory_address_p (SImode, plus_constant (xoperands[0], size))
  1307.           && memory_address_p (SImode, plus_constant (xoperands[1], size)))
  1308.         {
  1309.           /* We will store different integers into this particular RTX.  */
  1310.           xoperands[2] = gen_rtx (CONST_INT, VOIDmode, 13);
  1311.           for (i = (size>>2)-1; i >= 0; i--)
  1312.         {
  1313.           INTVAL (xoperands[2]) = i<<2;
  1314.           output_asm_insn ("ld [%a1+%2],%%g1\n\tst %%g1,[%a0+%2]",
  1315.                    xoperands);
  1316.         }
  1317.           return "";
  1318.         }
  1319.     }
  1320.     }
  1321.  
  1322.   /* This is the size of the transfer.
  1323.      Either use the register which already contains the size,
  1324.      or use a free register (used by no operands).
  1325.      Also emit code to decrement the size value by ALIGN.  */
  1326.   output_size_for_block_move (operands[2], temp1, alignrtx);
  1327.      
  1328.   zoperands[0] = operands[0];
  1329.   zoperands[3] = plus_constant (operands[0], align);
  1330.   output_load_address (zoperands);
  1331.  
  1332.   xoperands[3] = gen_rtx (CONST_INT, VOIDmode, movstrsi_label++);
  1333.   xoperands[4] = gen_rtx (CONST_INT, VOIDmode, align);
  1334.  
  1335.   if (align == 1)
  1336.     output_asm_insn ("\nLm%3:\n\tldub [%1+%2],%%g1\n\tsubcc %2,%4,%2\n\tbge Lm%3\n\tstb %%g1,[%0+%2]", xoperands);
  1337.   else if (align == 2)
  1338.     output_asm_insn ("\nLm%3:\n\tlduh [%1+%2],%%g1\n\tsubcc %2,%4,%2\n\tbge Lm%3\n\tsth %%g1,[%0+%2]", xoperands);
  1339.   else
  1340.     output_asm_insn ("\nLm%3:\n\tld [%1+%2],%%g1\n\tsubcc %2,%4,%2\n\tbge Lm%3\n\tst %%g1,[%0+%2]", xoperands);
  1341.   return "";
  1342. }
  1343.  
  1344. /* What the sparc lacks in hardware, make up for in software.
  1345.    Compute a fairly good sequence of shift and add insns
  1346.    to make a multiply happen.  */
  1347.  
  1348. #define ABS(x) ((x) < 0 ? -(x) : x)
  1349.  
  1350. char *
  1351. output_mul_by_constant (insn, operands, unsignedp)
  1352.      rtx insn;
  1353.      rtx *operands;
  1354.      int unsignedp;
  1355. {
  1356.   int c;            /* Size of constant */
  1357.   int shifts[BITS_PER_WORD];    /* Table of shifts */
  1358.   unsigned int p, log;        /* A power of two, and its log */
  1359.   int d1, d2;            /* Differences of c and p */
  1360.   int first = 1;        /* True if dst has unknown data in it */
  1361.   int i;
  1362.  
  1363.   CC_STATUS_INIT;
  1364.  
  1365.   c = INTVAL (operands[2]);
  1366.   if (c == 0)
  1367.     {
  1368.       /* Does happen, at least when not optimizing.  */
  1369.       if (GET_CODE (operands[0]) == MEM)
  1370.     return "st %%g0,%0";
  1371.       return "mov %%g0,%0";
  1372.     }
  1373.  
  1374.   output_asm_insn ("! start open coded multiply");
  1375.  
  1376.   /* Clear out the table of shifts. */
  1377.   for (i = 0; i < BITS_PER_WORD; ++i)
  1378.     shifts[i] = 0;
  1379.  
  1380.   while (c)
  1381.     {
  1382.       /* Find the power of two nearest ABS(c) */
  1383.       p = 1, log = 0;
  1384.       do
  1385.     {
  1386.       d1 = ABS(c) - p;
  1387.       p *= 2;
  1388.       ++log;
  1389.     }
  1390.       while (p < ABS(c));
  1391.       d2 = p - ABS(c);
  1392.  
  1393.       /* Make an appropriate entry in shifts for p. */
  1394.       if (d2 < d1)
  1395.     {
  1396.       shifts[log] = c < 0 ? -1 : 1;
  1397.       c = c < 0 ? d2 : -d2;
  1398.     }
  1399.       else
  1400.     {
  1401.       shifts[log - 1] = c < 0 ? -1 : 1;
  1402.       c = c < 0 ? -d1 : d1;
  1403.     }
  1404.     }
  1405.  
  1406.   /* Take care of the first insn in sequence.
  1407.      We know we have at least one. */
  1408.  
  1409.   /* A value of -1 in shifts says to subtract that power of two, and a value
  1410.      of 1 says to add that power of two. */
  1411.   for (i = 0; ; i++)
  1412.     if (shifts[i])
  1413.       {
  1414.     if (i)
  1415.       {
  1416.         operands[2] = gen_rtx (CONST_INT, VOIDmode, i);
  1417.         output_asm_insn ("sll %1,%2,%%g1", operands);
  1418.       }
  1419.     else output_asm_insn ("mov %1,%%g1", operands);
  1420.  
  1421.     log = i;
  1422.     if (shifts[i] < 0)
  1423.       output_asm_insn ("sub %%g0,%%g1,%0", operands);
  1424.     else
  1425.       output_asm_insn ("mov %%g1,%0", operands);
  1426.     break;
  1427.       }
  1428.  
  1429.   /* A value of -1 in shifts says to subtract that power of two, and a value
  1430.      of 1 says to add that power of two--continued.  */
  1431.   for (i += 1; i < BITS_PER_WORD; ++i)
  1432.     if (shifts[i])
  1433.       {
  1434.     if (i - log > 0)
  1435.       {
  1436.         operands[2] = gen_rtx (CONST_INT, VOIDmode, i - log);
  1437.         output_asm_insn ("sll %%g1,%2,%%g1", operands);
  1438.       }
  1439.     else
  1440.       {
  1441.         operands[2] = gen_rtx (CONST_INT, VOIDmode, log - i);
  1442.         output_asm_insn ("sra %%g1,%2,%%g1", operands);
  1443.       }
  1444.     log = i;
  1445.     if (shifts[i] < 0)
  1446.       output_asm_insn ("sub %0,%%g1,%0", operands);
  1447.     else
  1448.       output_asm_insn ("add %0,%%g1,%0", operands);
  1449.       }
  1450.  
  1451.   output_asm_insn ("! end open coded multiply");
  1452.  
  1453.   return "";
  1454. }
  1455.  
  1456. char *
  1457. output_mul_insn (operands, unsignedp)
  1458.      rtx *operands;
  1459.      int unsignedp;
  1460. {
  1461.   int lucky1 = ((unsigned)REGNO (operands[1]) - 8) <= 1;
  1462.   int lucky2 = ((unsigned)REGNO (operands[2]) - 8) <= 1;
  1463.  
  1464.   CC_STATUS_INIT;
  1465.  
  1466.   if (lucky1)
  1467.     {
  1468.       if (lucky2)
  1469.     {
  1470.       if (REGNO (operands[1]) == REGNO (operands[2]))
  1471.         {
  1472.           if (REGNO (operands[1]) == 8)
  1473.         output_asm_insn ("mov %%o0,%%o1");
  1474.           else
  1475.         output_asm_insn ("mov %%o1,%%o0");
  1476.         }
  1477.       output_asm_insn ("call .mul,2\n\tnop", operands);
  1478.     }
  1479.       else
  1480.     {
  1481.       rtx xoperands[2];
  1482.       xoperands[0] = gen_rtx (REG, SImode,
  1483.                   8 ^ (REGNO (operands[1]) == 8));
  1484.       xoperands[1] = operands[2];
  1485.       output_asm_insn ("call .mul,2\n\tmov %1,%0", xoperands);
  1486.     }
  1487.     }
  1488.   else if (lucky2)
  1489.     {
  1490.       rtx xoperands[2];
  1491.       xoperands[0] = gen_rtx (REG, SImode,
  1492.                   8 ^ (REGNO (operands[2]) == 8));
  1493.       xoperands[1] = operands[1];
  1494.       output_asm_insn ("call .mul,2\n\tmov %1,%0", xoperands);
  1495.     }
  1496.   else
  1497.     {
  1498.       output_asm_insn ("mov %1,%%o0\n\tcall .mul,2\n\tmov %2,%%o1",
  1499.                operands);
  1500.     }
  1501.  
  1502.   if (REGNO (operands[0]) == 8)
  1503.     return "";
  1504.   return "mov %%o0,%0";
  1505. }
  1506.  
  1507. /* Make floating point register f0 contain 0.
  1508.    SIZE is the number of registers (including f0)
  1509.    which should contain 0.  */
  1510.  
  1511. void
  1512. make_f0_contain_0 (size)
  1513.      int size;
  1514. {
  1515.   if (size == 1)
  1516.     {
  1517.       if ((cc_status.flags & (CC_F0_IS_0)) == 0)
  1518.     output_asm_insn ("ld [%%fp-16],%%f0", 0);
  1519.       cc_status.flags |= CC_F0_IS_0;
  1520.     }
  1521.   else if (size == 2)
  1522.     {
  1523.       if ((cc_status.flags & CC_F0_IS_0) == 0)
  1524.     output_asm_insn ("ld [%%fp-16],%%f0", 0);
  1525.       if ((cc_status.flags & (CC_F1_IS_0)) == 0)
  1526.     output_asm_insn ("ld [%%fp-12],%%f1", 0);
  1527.       cc_status.flags |= CC_F0_IS_0 | CC_F1_IS_0;
  1528.     }
  1529. }
  1530.  
  1531. /* Since condition codes don't have logical links, we need to keep
  1532.    their setting and use together for set-cc insns.  */
  1533. void
  1534. gen_scc_insn (code, mode, operands)
  1535.      enum rtx_code code;
  1536.      enum machine_mode mode;
  1537.      rtx *operands;
  1538. {
  1539.   extern rtx sequence_stack;
  1540.   rtx last_insn = XEXP (XEXP (sequence_stack, 1), 0);
  1541.   rtx last_pat;
  1542.  
  1543.   /* Skip back over the CLOBBERs that may precede this insn.  */
  1544.   while (last_insn && GET_CODE (last_insn) == INSN
  1545.      && GET_CODE (PATTERN (last_insn)) == CLOBBER)
  1546.     last_insn = PREV_INSN (last_insn);
  1547.   /* We should have found the preceding compare.  */
  1548.   if (last_insn == 0 || GET_CODE (last_insn) != INSN)
  1549.     abort ();
  1550.   last_pat = PATTERN (last_insn);
  1551.   if (GET_CODE (last_pat) != SET
  1552.       || GET_CODE (SET_DEST (last_pat)) != CC0)
  1553.     abort ();
  1554.  
  1555.   /* Turn off that previous insn, now that we have got the data out of it.  */
  1556.   PUT_CODE (last_insn, NOTE);
  1557.   NOTE_LINE_NUMBER (last_insn) = NOTE_INSN_DELETED;
  1558.  
  1559.   /* Emit one replacement insn to compare operands and store result.  */
  1560.   emit_insn (gen_rtx (SET, VOIDmode, operands[0],
  1561.               gen_rtx (code, mode, SET_SRC (last_pat), const0_rtx)));
  1562. }
  1563.  
  1564. /* Output reasonable peephole for set-on-condition-code insns.
  1565.    Note that these insns assume a particular way of defining
  1566.    labels.  Therefore, *both* tm-sparc.h and this function must
  1567.    be changed if a new syntax is needed.  */
  1568.  
  1569. char *
  1570. output_scc_insn (code, operand)
  1571.      enum rtx_code code;
  1572.      rtx operand;
  1573. {
  1574.   rtx xoperands[2];
  1575.   rtx label = gen_label_rtx ();
  1576.   int cc_in_fccr = cc_status.flags & CC_IN_FCCR;
  1577.   int antisymmetric = 0;
  1578.  
  1579.   xoperands[0] = operand;
  1580.   xoperands[1] = label;
  1581.  
  1582.   switch (code)
  1583.     {
  1584.     case NE:
  1585.       if (cc_in_fccr)
  1586.     output_asm_insn ("fbne,a %l0", &label);
  1587.       else
  1588.     output_asm_insn ("bne,a %l0", &label);
  1589.       break;
  1590.     case EQ:
  1591.       if (cc_in_fccr)
  1592.     output_asm_insn ("fbe,a %l0", &label);
  1593.       else
  1594.     output_asm_insn ("be,a %l0", &label);
  1595.       break;
  1596.     case GE:
  1597.       if (cc_in_fccr)
  1598.     output_asm_insn ("fbge,a %l0", &label);
  1599.       else
  1600.     output_asm_insn ("bge,a %l0", &label);
  1601.       antisymmetric = 1;
  1602.       break;
  1603.     case GT:
  1604.       if (cc_in_fccr)
  1605.     output_asm_insn ("fbg,a %l0", &label);
  1606.       else
  1607.     output_asm_insn ("bg,a %l0", &label);
  1608.       antisymmetric = 1;
  1609.       break;
  1610.     case LE:
  1611.       if (cc_in_fccr)
  1612.     output_asm_insn ("fble,a %l0", &label);
  1613.       else
  1614.     output_asm_insn ("ble,a %l0", &label);
  1615.       antisymmetric = 1;
  1616.       break;
  1617.     case LT:
  1618.       if (cc_in_fccr)
  1619.     output_asm_insn ("fbl,a %l0", &label);
  1620.       else
  1621.     output_asm_insn ("bl,a %l0", &label);
  1622.       antisymmetric = 1;
  1623.       break;
  1624.     case GEU:
  1625.       if (cc_in_fccr)
  1626.     abort ();
  1627.       else
  1628.     output_asm_insn ("bgeu,a %l0", &label);
  1629.       antisymmetric = 1;
  1630.       break;
  1631.     case GTU:
  1632.       if (cc_in_fccr)
  1633.     abort ();
  1634.       else
  1635.     output_asm_insn ("bgu,a %l0", &label);
  1636.       antisymmetric = 1;
  1637.       break;
  1638.     case LEU:
  1639.       if (cc_in_fccr)
  1640.     abort ();
  1641.       else
  1642.     output_asm_insn ("bleu,a %l0", &label);
  1643.       antisymmetric = 1;
  1644.       break;
  1645.     case LTU:
  1646.       if (cc_in_fccr)
  1647.     abort ();
  1648.       else
  1649.     output_asm_insn ("blu,a %l0", &label);
  1650.       antisymmetric = 1;
  1651.       break;
  1652.     default:
  1653.       abort ();
  1654.     }
  1655.   if (antisymmetric
  1656.       && (cc_status.flags & CC_REVERSED))
  1657.     output_asm_insn ("orcc %%g0,0,%0\n\torcc %%g0,1,%0\n%l1:", xoperands);
  1658.   else
  1659.     output_asm_insn ("orcc %%g0,1,%0\n\torcc %%g0,0,%0\n%l1:", xoperands);
  1660.   return "";
  1661. }
  1662.  
  1663. /* Output a delayed branch insn with the delay insn in its
  1664.    branch slot.  The delayed branch insn template is in TEMPLATE,
  1665.    with operands OPERANDS.  The insn in its delay slot is INSN.
  1666.  
  1667.    As a special case, since we know that all memory transfers are via
  1668.    ld/st insns, if we see a (MEM (SYMBOL_REF ...)) we divide the memory
  1669.    reference around the branch as
  1670.  
  1671.     sethi %hi(x),%%g1
  1672.     b ...
  1673.     ld/st [%g1+%lo(x)],...
  1674.  
  1675.    As another special case, we handle loading (SYMBOL_REF ...) and
  1676.    other large constants around branches as well:
  1677.  
  1678.     sethi %hi(x),%0
  1679.     b ...
  1680.     or %0,%lo(x),%1
  1681.  
  1682.    */
  1683.  
  1684. char *
  1685. output_delayed_branch (template, operands, insn)
  1686.      char *template;
  1687.      rtx *operands;
  1688.      rtx insn;
  1689. {
  1690.   extern rtx recog_operand[];
  1691.   rtx src = XVECEXP (PATTERN (insn), 0, 1);
  1692.   rtx dest = XVECEXP (PATTERN (insn), 0, 0);
  1693.  
  1694.   if (GET_CODE (src) == SYMBOL_REF
  1695.       || (GET_CODE (src) == CONST_INT
  1696.       && !(SMALL_INT (src) || (INTVAL (src) & 0x3ff) == 0)))
  1697.     {
  1698.       rtx xoperands[2];
  1699.       xoperands[0] = dest;
  1700.       xoperands[1] = src;
  1701.  
  1702.       /* Output the `sethi' insn.  */
  1703.       output_asm_insn ("sethi %%hi(%1),%0", xoperands);
  1704.  
  1705.       /* Output the branch instruction next.  */
  1706.       output_asm_insn (template, operands);
  1707.  
  1708.       /* Now output the `or' insn.  */
  1709.       output_asm_insn ("or %0,%%lo(%1),%0", xoperands);
  1710.     }
  1711.   else if ((GET_CODE (src) == MEM
  1712.         && CONSTANT_ADDRESS_P (XEXP (src, 0)))
  1713.        || (GET_CODE (dest) == MEM
  1714.            && CONSTANT_ADDRESS_P (XEXP (dest, 0))))
  1715.     {
  1716.       rtx xoperands[2];
  1717.       char *split_template;
  1718.       xoperands[0] = dest;
  1719.       xoperands[1] = src;
  1720.  
  1721.       /* Output the `sethi' insn.  */
  1722.       if (GET_CODE (src) == MEM)
  1723.     {
  1724.       if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  1725.          && cc_prev_status.mdep == XEXP (operands[1], 0)))
  1726.         output_asm_insn ("sethi %%hi(%m1),%%g1", xoperands);
  1727.       split_template = "ld [%%g1+%%lo(%m1)],%0";
  1728.     }
  1729.       else
  1730.     {
  1731.       if (! ((cc_prev_status.flags & CC_KNOW_HI_G1)
  1732.          && cc_prev_status.mdep == XEXP (operands[0], 0)))
  1733.         output_asm_insn ("sethi %%hi(%m0),%%g1", xoperands);
  1734.       split_template = "st %r1,[%%g1+%%lo(%m0)]";
  1735.     }
  1736.  
  1737.       /* Output the branch instruction next.  */
  1738.       output_asm_insn (template, operands);
  1739.  
  1740.       /* Now output the load or store.
  1741.      No need to do a CC_STATUS_INIT, because we are branching anyway.  */
  1742.       output_asm_insn (split_template, xoperands);
  1743.     }
  1744.   else
  1745.     {
  1746.       extern char *insn_template[];
  1747.       extern char *(*insn_outfun[])();
  1748.       int insn_code_number;
  1749.       rtx pat = gen_rtx (SET, VOIDmode, dest, src);
  1750.       rtx delay_insn = gen_rtx (INSN, VOIDmode, 0, 0, 0, pat, -1, 0, 0);
  1751.       int i;
  1752.       extern rtx alter_subreg();
  1753.       extern int insn_n_operands[];
  1754.  
  1755.       /* Output the branch instruction first.  */
  1756.       output_asm_insn (template, operands);
  1757.  
  1758.       /* Now recognize the insn which we put in its delay slot.
  1759.      We must do this after outputing the branch insn,
  1760.      since operands may just be a pointer to `recog_operand'.  */
  1761.       insn_code_number = recog (pat, delay_insn);
  1762.       if (insn_code_number == -1)
  1763.     abort ();
  1764.  
  1765.       for (i = 0; i < insn_n_operands[insn_code_number]; i++)
  1766.     {
  1767.       if (GET_CODE (recog_operand[i]) == SUBREG)
  1768.         recog_operand[i] = alter_subreg (recog_operand[i]);
  1769.     }
  1770.  
  1771.       /* Now get the template for what this insn would
  1772.      have been, without the branch.  Its operands are
  1773.      exactly the same as they would be, so we don't
  1774.      need to do an insn_extract.  */
  1775.       template = insn_template[insn_code_number];
  1776.       if (template == 0)
  1777.     template = (*insn_outfun[insn_code_number]) (recog_operand, delay_insn);
  1778.       output_asm_insn (template, recog_operand);
  1779.     }
  1780.   CC_STATUS_INIT;
  1781.   return "";
  1782. }
  1783.  
  1784. /* Output a newly constructed insn DELAY_INSN.  */
  1785. char *
  1786. output_delay_insn (delay_insn)
  1787.      rtx delay_insn;
  1788. {
  1789.   char *template;
  1790.   extern rtx recog_operand[];
  1791.   extern char call_used_regs[];
  1792.   extern char *insn_template[];
  1793.   extern int insn_n_operands[];
  1794.   extern char *(*insn_outfun[])();
  1795.   extern rtx alter_subreg();
  1796.   int insn_code_number;
  1797.   extern int insn_n_operands[];
  1798.   int i;
  1799.  
  1800.   /* Now recognize the insn which we put in its delay slot.
  1801.      We must do this after outputing the branch insn,
  1802.      since operands may just be a pointer to `recog_operand'.  */
  1803.   insn_code_number = recog_memoized (delay_insn);
  1804.   if (insn_code_number == -1)
  1805.     abort ();
  1806.  
  1807.   /* Extract the operands of this delay insn.  */
  1808.   INSN_CODE (delay_insn) = insn_code_number;
  1809.   insn_extract (delay_insn);
  1810.  
  1811.   /* It is possible that this insn has not been properly scaned by final
  1812.      yet.  If this insn's operands don't appear in the peephole's
  1813.      actual operands, then they won't be fixed up by final, so we
  1814.      make sure they get fixed up here.  -- This is a kludge.  */
  1815.   for (i = 0; i < insn_n_operands[insn_code_number]; i++)
  1816.     {
  1817.       if (GET_CODE (recog_operand[i]) == SUBREG)
  1818.     recog_operand[i] = alter_subreg (recog_operand[i]);
  1819.     }
  1820.  
  1821. #ifdef REGISTER_CONSTRAINTS
  1822.   if (! constrain_operands (insn_code_number))
  1823.     abort ();
  1824. #endif
  1825.  
  1826.   cc_prev_status = cc_status;
  1827.  
  1828.   /* Update `cc_status' for this instruction.
  1829.      The instruction's output routine may change it further.
  1830.      If the output routine for a jump insn needs to depend
  1831.      on the cc status, it should look at cc_prev_status.  */
  1832.  
  1833.   NOTICE_UPDATE_CC (PATTERN (delay_insn), delay_insn);
  1834.  
  1835.   /* Now get the template for what this insn would
  1836.      have been, without the branch.  */
  1837.  
  1838.   template = insn_template[insn_code_number];
  1839.   if (template == 0)
  1840.     template = (*insn_outfun[insn_code_number]) (recog_operand, delay_insn);
  1841.   output_asm_insn (template, recog_operand);
  1842.   return "";
  1843. }
  1844.  
  1845. /* Output the insn HEAD, keeping OPERANDS protected (wherever they are).
  1846.    HEAD comes from the target of some branch, so before we output it,
  1847.    we delete it from the target, lest we execute it twice.  The caller
  1848.    of this function promises that such code motion is permissable.  */
  1849. char *
  1850. output_eager_then_insn (head, operands)
  1851.      rtx head;
  1852.      rtx *operands;
  1853. {
  1854.   extern rtx alter_subreg ();
  1855.   extern int insn_n_operands[];
  1856.   extern rtx recog_operand[];
  1857.   rtx xoperands[MAX_RECOG_OPERANDS];
  1858.   int insn_code_number, i, nbytes;
  1859.   rtx nhead;
  1860.  
  1861.   /* Micro-hack: run peephole on head if it looks like a good idea.
  1862.      Right now there's only one such case worth doing...
  1863.  
  1864.      This could be made smarter if the peephole for ``2-insn combine''
  1865.      were also made smarter.  */
  1866.   if (GET_CODE (PATTERN (head)) == SET
  1867.       && REG_P (SET_SRC (PATTERN (head)))
  1868.       && REG_P (SET_DEST (PATTERN (head)))
  1869.       && (nhead = next_real_insn_no_labels (head))
  1870.       && GET_CODE (nhead) == INSN
  1871.       && GET_CODE (PATTERN (nhead)) == SET
  1872.       && GET_CODE (SET_DEST (PATTERN (nhead))) == CC0
  1873.       && (SET_SRC (PATTERN (nhead)) == SET_SRC (PATTERN (head))
  1874.       || SET_SRC (PATTERN (nhead)) == SET_DEST (PATTERN (head))))
  1875.     /* Something's wrong if this does not fly.  */
  1876.     if (! peephole (head))
  1877.       abort ();
  1878.  
  1879.   /* Save our contents of `operands', since output_delay_insn sets them.  */
  1880.   insn_code_number = recog_memoized (head);
  1881.   nbytes = insn_n_operands[insn_code_number] * sizeof (rtx);
  1882.   bcopy (operands, xoperands, nbytes);
  1883.  
  1884.   /* Output the delay insn, and prevent duplication later.  */
  1885.   delete_insn (head);
  1886.   output_delay_insn (head);
  1887.  
  1888.   /* Restore this insn's operands.  */
  1889.   bcopy (xoperands, operands, nbytes);
  1890. }
  1891.  
  1892. /* Return the next INSN, CALL_INSN or JUMP_INSN after LABEL;
  1893.    or 0, if there is none.  Also return 0 if we cross a label.  */
  1894.  
  1895. rtx
  1896. next_real_insn_no_labels (label)
  1897.      rtx label;
  1898. {
  1899.   register rtx insn = NEXT_INSN (label);
  1900.   register RTX_CODE code;
  1901.  
  1902.   while (insn)
  1903.     {
  1904.       code = GET_CODE (insn);
  1905.       if (code == INSN)
  1906.     {
  1907.       if (GET_CODE (PATTERN (insn)) != CLOBBER
  1908.           && GET_CODE (PATTERN (insn)) != USE)
  1909.         return insn;
  1910.     }
  1911.       if (code == CALL_INSN || code == JUMP_INSN)
  1912.     return insn;
  1913.       if (code == CODE_LABEL)
  1914.     return 0;
  1915.       insn = NEXT_INSN (insn);
  1916.     }
  1917.  
  1918.   return 0;
  1919. }
  1920.  
  1921. int
  1922. operands_satisfy_eager_branch_peephole (operands, conditional)
  1923.      rtx *operands;
  1924.      int conditional;
  1925. {
  1926.   rtx label;
  1927.  
  1928.   if (conditional)
  1929.     {
  1930.       if (GET_CODE (operands[0]) != IF_THEN_ELSE)
  1931.     return 0;
  1932.  
  1933.       if (GET_CODE (XEXP (operands[0], 1)) == LABEL_REF)
  1934.     label = XEXP (XEXP (operands[0], 1), 0);
  1935.       else if (GET_CODE (XEXP (operands[0], 2)) == LABEL_REF)
  1936.     label = XEXP (XEXP (operands[0], 2), 0);
  1937.       else return 0;
  1938.     }
  1939.   else
  1940.     {
  1941.       label = operands[0];
  1942.     }
  1943.  
  1944.   if (LABEL_NUSES (label) == 1)
  1945.     {
  1946.       rtx prev = PREV_INSN (label);
  1947.       while (prev && GET_CODE (prev) == NOTE)
  1948.     prev = PREV_INSN (prev);
  1949.       if (prev == 0
  1950.       || GET_CODE (prev) == BARRIER)
  1951.     {
  1952.       rtx head = next_real_insn_no_labels (label);
  1953.  
  1954.       if (head
  1955.           && ! INSN_DELETED_P (head)
  1956.           && GET_CODE (head) == INSN
  1957.           && GET_CODE (PATTERN (head)) == SET
  1958.           && strict_single_insn_op_p (SET_SRC (PATTERN (head)),
  1959.                       GET_MODE (SET_DEST (PATTERN (head))))
  1960.           && strict_single_insn_op_p (SET_DEST (PATTERN (head)),
  1961.                       GET_MODE (SET_DEST (PATTERN (head))))
  1962.           /* Moves between FP regs and CPU regs are two insns.  */
  1963.           && !(GET_CODE (SET_SRC (PATTERN (head))) == REG
  1964.            && GET_CODE (SET_DEST (PATTERN (head))) == REG
  1965.            && (FP_REG_P (SET_SRC (PATTERN (head)))
  1966.                != FP_REG_P (SET_DEST (PATTERN (head))))))
  1967.         {
  1968.           if (conditional == 2)
  1969.         return (GET_CODE (operands[1]) != PC
  1970.             && safe_insn_src_p (operands[2], VOIDmode)
  1971.             && strict_single_insn_op_p (operands[2], VOIDmode)
  1972.             && operand_clobbered_before_used_after (operands[1], label));
  1973.           return 1;
  1974.         }
  1975.     }
  1976.     }
  1977.  
  1978.   if (conditional == 1
  1979.       && GET_CODE (operands[1]) != PC
  1980.       && safe_insn_src_p (operands[2], VOIDmode)
  1981.       && strict_single_insn_op_p (operands[2], VOIDmode)
  1982.       && operand_clobbered_before_used_after (operands[1], label))
  1983.     return 1;
  1984.  
  1985.   return 0;
  1986. }
  1987.  
  1988.